package MyDFS;

/**
 * 79. 单词搜索
 *
 * 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中，返回 true ；否则，返回 false 。
 *
 * 单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
 *
 * 示例 1：
 *
 * 输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
 * 输出：true
 */
public class Leetcode0079 {
    public static boolean exist(char[][] board, String word) {
        // 1 <= word.length <= 15
        if(board.length <=0 || board[0].length <=0 ){
            return false;
        }

        // 预处理剪枝
        boolean[] hasW = new boolean[80];
        for(int i=0; i<board.length; i++){
            for(int j=0; j<board[0].length; j++){
                hasW[board[i][j] - 'A'] = true;
            }
        }
        for(int i=0; i<word.length(); i++){
            if(!hasW[word.charAt(i) - 'A']){
                return false;
            }
        }

        for(int i=0; i<board.length; i++){
            for(int j=0; j<board[0].length; j++){
                if(board[i][j] == word.charAt(0)){
                    System.out.println(i + " " +j);
                    boolean isTrue = hasWord(board, word, i, j);
                    System.out.println(isTrue);
                    if(isTrue){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static boolean hasWord(char[][] board, String word, int i, int j){
        // int[][] newBoard = board.clone();
        boolean [][] used = new boolean[board.length][board[0].length];
        used[i][j] = true;
        System.out.println("===" + i + " "+j);
        int len = word.length();
        if(word.length() == 1){
            return true;
        }

        return dfs(board, word, used, len, 1, i+1, j) || dfs(board, word, used, len, 1, i-1, j) || dfs(board, word, used, len, 1, i, j+1) || dfs(board, word, used, len, 1, i, j-1);
    }

    public static boolean dfs(char[][] board, String word, boolean [][] used, int len, int idx, int i, int j){

        if(idx == len){
            return true;
        }
        if(i<0 || j<0 || i>= board.length || j>=board[0].length || board[i][j]!=word.charAt(idx)){
            return false;
        }
        System.out.println(i + " "+j + " " +idx);
        if(used[i][j]){
            System.out.println("used" + i + " "+j);
            return false;
        }

        // 需要 深拷贝， 浅拷贝 会出问题
        boolean [][] newUsed1 = new boolean[board.length][board[0].length];
        for(int mm=0; mm<board.length; mm++){
            for(int nn=0; nn<board[0].length; nn++){
                newUsed1[mm][nn] = used[mm][nn];
            }
        }
        newUsed1[i][j] = true;


        return dfs(board, word, newUsed1, len, idx+1, i+1, j) || dfs(board, word, newUsed1, len, idx+1, i-1, j) || dfs(board, word, newUsed1, len, idx+1, i, j+1) || dfs(board, word, newUsed1, len, idx+1, i, j-1);

    }

    public static void main(String[] args) {
        char[][] ss = new char[][] {
                {'A','B','C','E'},
                {'S','F','C','S'},
                {'A','D','E','E'}
        };

        String aa= "ABCCED";
        System.out.println(exist(ss, aa));
    }
}
